﻿using AutoMapper;
using IOA.MES.Common;
using IOA.MES.DataAccess.Entity;
using IOA.MES.DataAccess.Enum;
using IOA.MES.DataAccess.VModel;
using IOA.MES.Log.Business;
using IOA.MES.Log.DataAccess.VModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOA.MES.Business
{
    /// <summary>
    /// 装车管理（错误代码：136001）
    /// </summary>
    public class LoadMgr
    {
        private MESContext mesDb = new MESContext("MES");

        /// <summary>
        /// 装车
        /// </summary>
        /// <param name="model">包装</param>
        /// <param name="forceLoad">强行装车</param>
        public void LoadPack(VLoadPack model)
        {
            var loadInspect = mesDb.LoadInspects.FirstOrDefault(_ => _.PkId == model.LoadId && _.Valid);
            if (loadInspect == null)
            {
                throw new MultiLanBizException(136006);//入库检不存在
            }
            var pack = mesDb.Packs.AsNoTracking().FirstOrDefault(_ => _.PackNo == model.PackNo && _.Valid);
            if (pack == null)
            {
                throw new MultiLanBizException(136001, model.PackNo);//包装不存在
            }
            else if (pack.PackStatus == PackStatus.Unpack)
            {
                throw new MultiLanBizException(136002, model.PackNo);//包装已解包，无法装车
            }
            else if (pack.PackStatus == PackStatus.Packing)
            {
                throw new MultiLanBizException(136003, model.PackNo);//打包未完成
            }
            else if (pack.StockStatus != PackStockStatus.Outbound)
            {
                throw new MultiLanBizException(136004, model.PackNo);//包装未完成出库
            }

            var loadPack = mesDb.LoadPacks.AsNoTracking().FirstOrDefault(_ => _.LoadId == model.LoadId && _.PackNo == model.PackNo && _.Valid);
            if (loadPack == null)
            {
                throw new MultiLanBizException(136008);//柜号不正确，无法入库
            }
            else if (loadPack.Loaded)
            {
                throw new MultiLanBizException(136005, model.PackNo);//包装已装车，无法重复操作
            }

            mesDb.LoadPacks.Attach(loadPack);
            loadPack.Loaded = true;
            loadPack.ModifyBy = model.ModifyBy;
            loadPack.ModifyTime = DateTime.Now;

            mesDb.LoadInspects.Attach(loadInspect);
            loadInspect.LoadedQuantity = loadInspect.LoadedQuantity + 1;
            loadInspect.LoadBy = model.ModifyBy;
            loadInspect.ModifyBy = model.ModifyBy;
            loadInspect.ModifyTime = DateTime.Now;
            mesDb.SaveChanges();

            new TaskFactory().StartNew(() =>
             {
                 var components = mesDb.Components.AsNoTracking().Where(_ => _.PackNo == model.PackNo && _.Valid).ToList();

                 var users = new UserMgr().QueryUsers(new List<int> { model.ModifyBy });
                 var logs = components.Select(_ => new VOprLog
                 {
                     SubjectType = "组件",
                     SubjectNo = _.BarCode,
                     LogName = "组件装车",
                     LogStatus = "正常",
                     OpeatorId = model.CreateBy,
                     OpeatorName = users.FirstOrDefault()?.TrueName,
                     LogContent = $"组件装车",
                     LogTime = DateTime.Now,
                     CreateBy = model.CreateBy
                 }).ToList();
                 new OprLogMgr().AddLogs(logs);
             });
        }

        /// <summary>
        /// 完成装车
        /// </summary>
        /// <param name="model">装车对象</param>
        public void FinishLoad(VLoadInspect model)
        {
            var load = mesDb.LoadInspects.FirstOrDefault(_ => _.PkId == model.PkId && _.Valid);
            if (load == null)
            {
                throw new MultiLanBizException(136009);//装车检记录不存在
            }
            else if (load.LoadStatus == DataAccess.Enum.LoadStatus.Loaded)
            {
                throw new MultiLanBizException(136010);//装车检已完成，无法重复操作
            }

            load.LoadStatus = LoadStatus.Loaded;
            load.Driver = model.Driver;
            load.Phone = model.Phone;
            load.NumberPlate = model.NumberPlate;
            load.ActualCabinetNo = model.ActualCabinetNo;
            load.LockNo = model.LockNo;
            load.LoadBy = model.ModifyBy;
            load.FinishTime = DateTime.Now;
            load.ModifyBy = model.ModifyBy;
            load.ModifyTime = DateTime.Now;

            mesDb.SaveChanges();
        }

        /// <summary>
        /// 移除装车包装
        /// </summary>
        /// <param name="model">包装对象</param>
        public void UnloadPack(LoadPack model)
        {
            var loadPack = mesDb.LoadPacks.FirstOrDefault(_ => _.LoadId == model.LoadId && _.PackNo == model.PackNo && _.Valid);
            if (loadPack == null)
            {
                throw new MultiLanBizException(136011, model.PackNo);//当前包装不在本次装车中
            }

            var load = mesDb.LoadInspects.FirstOrDefault(_ => _.PkId == loadPack.LoadId && _.Valid);
            if (load != null)
            {
                if (load.LoadStatus == DataAccess.Enum.LoadStatus.Loaded)
                {
                    throw new MultiLanBizException(136012, model.PackNo);//本次装车已完成，无法移除包装
                }
                mesDb.LoadInspects.Attach(load);
                load.Quantity = load.Quantity - 1;
                load.ModifyBy = model.ModifyBy;
                load.ModifyTime = DateTime.Now;
            }

            mesDb.LoadPacks.Attach(loadPack);
            loadPack.Valid = false;
            loadPack.ModifyBy = model.ModifyBy;
            loadPack.ModifyTime = DateTime.Now;

            mesDb.SaveChanges();
        }

        /// <summary>
        /// 查询装车记录
        /// </summary>
        /// <param name="pageIndex">页面索引</param>
        /// <param name="pageSize">页面容量</param>
        /// <param name="total">全部数量</param>
        /// <param name="userId">装车人</param>
        /// <returns>装车记录列表</returns>
        public List<VLoadInspect> QueryLoads(int pageIndex, int pageSize, out int total, LoadStatus? loadStatus = null, int userId = 0)
        {
            var query = mesDb.LoadInspects.AsNoTracking().Where(_ => _.Valid);
            if (userId > 0)
            {
                query = query.Where(_ => _.LoadBy == userId);
            }
            if (loadStatus.HasValue)
            {
                query = query.Where(_ => _.LoadStatus == loadStatus.Value);
            }
            total = query.Count();
            query = query.OrderBy(_ => _.LoadStatus).ThenByDescending(_ => _.PkId);
            var entities = pageSize <= 0 ? query.ToList() : query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            var models = Mapper.Map<List<VLoadInspect>>(entities);

            var userIds = models.Select(_ => _.LoadBy).Distinct().ToList();
            var users = userIds.Any() ? new UserMgr().QueryUsers(userIds) : new List<VUser>();

            models.ForEach(load =>
            {
                load.CNLoadBy = users.FirstOrDefault(_ => _.CreateBy == _.PkId)?.TrueName ?? string.Empty;
            });

            return models;
        }

        /// <summary>
        /// 查询装车记录
        /// </summary>
        /// <param name="loadId">装车ID</param>
        /// <returns>装车记录列表</returns>
        public VLoadInspect GetLoad(int loadId)
        {
            var entity = mesDb.LoadInspects.AsNoTracking().FirstOrDefault(_ => _.PkId == loadId && _.Valid);
            var model = Mapper.Map<VLoadInspect>(entity);

            if (model == null)
            {
                return null;
            }

            model.CNLoadBy = new UserMgr().QueryUsers(new List<int> { model.LoadBy }).FirstOrDefault()?.TrueName ?? string.Empty;
            var loadPacks = mesDb.LoadPacks.AsNoTracking().Where(_ => _.LoadId == loadId && _.Valid).ToList();
            model.Packs = Mapper.Map<List<VLoadPack>>(loadPacks);

            return model;
        }

        /// <summary>
        /// 查询装车检列表
        /// </summary>
        /// <param name="page">页面索引</param>
        /// <param name="limit">页面容量</param>
        /// <param name="total">全部数量</param>
        /// <param name="deliveryOrderNo">发货单号</param>
        /// <param name="startDate">开始日期</param>
        /// <param name="endDate">截止日期</param>
        /// <param name="status">装车状态</param>
        /// <returns>列表</returns>
        public List<VLoadInspect> QueryLoads(int page, int limit, out int total, string deliveryOrderNo, DateTime startDate, DateTime endDate, LoadStatus? status)
        {
            var query = mesDb.LoadInspects.AsNoTracking().Where(_ => _.Valid);
            if (!string.IsNullOrWhiteSpace(deliveryOrderNo))
            {
                query = query.Where(_ => _.DeliveryNo.Contains(deliveryOrderNo));
            }
            if (status.HasValue)
            {
                query = query.Where(_ => _.LoadStatus == status.Value);
            }
            total = query.Count();
            query = query.OrderBy(_ => _.LoadStatus).ThenByDescending(_ => _.PkId);
            var entities = limit <= 0 ? query.ToList() : query.Skip((page - 1) * limit).Take(limit).ToList();
            var models = Mapper.Map<List<VLoadInspect>>(entities);

            var userIds = models.Select(_ => _.LoadBy).Distinct().ToList();
            var users = userIds.Any() ? new UserMgr().QueryUsers(userIds) : new List<VUser>();

            models.ForEach(load =>
            {
                load.CNLoadBy = users.FirstOrDefault(_ => _.CreateBy == _.PkId)?.TrueName ?? string.Empty;
            });

            return models;
        }
    }
}
